# coding:utf8
import cv2
import numpy as np
import matplotlib.pyplot as plt
import sys

count = [0]


class char_range_t:
    def __init__(self):
        self.begin = None
        self.end = None


def save_cut(img, _id):
    cv2.imwrite(fr'E:\keras_research\tmp\ai_{_id}.jpg', img)


# 获取每个分割字符的范围，min_thresh：波峰的最小幅度，min_range：两个波峰的最小间隔
def Getpeekrange(v_pos, peek_range: list, min_thresh=2, min_range=5):
    """

    :param v_pos:
    :param peek_range:
    :param min_thresh:
    :param min_range:
    :return:
    """
    begin = 0
    end = 0
    # 对于每一列的值
    for i in range(len(v_pos)):
        # 黑点数多 为空白
        if v_pos[i] > min_thresh and begin == 0:
            begin = i
        elif v_pos[i] > min_thresh and begin != 0:
            continue
        elif v_pos[i] < min_thresh and begin != 0:
            print('h')
            end = i
            if end - begin >= min_range:
                tmp = char_range_t()
                tmp.begin = begin
                tmp.end = end
                peek_range.append(tmp)
                begin = 0
                end = 0
        elif v_pos[i] < min_thresh or begin == 0:
            continue
        else:
            print('raise geek error')
    return

def cutChar(img, v_peek_range, chars_set):
    """
    :param img:
    :param v_peek_range:list[char_range_t]
    :param h_peek_range:
    :param chars_set:
    :return:
    """
    global count
    show_img = img.copy()
    show_img = cv2.cvtColor(show_img, cv2.COLOR_GRAY2BGR)
    for i in range(len(v_peek_range)):
        # char_gap=v_peek_range[i].end - v_peek_range[i].begin
        x, y, w, h = v_peek_range[i].begin, 0, v_peek_range[i].end - v_peek_range[i].begin, img.shape[0]
        single_char = (show_img[y:h, x:w]).copy()
        chars_set.append(single_char)
        # save_cut(single_char, count)
        count[0] += 1

        # cv2.imshow('cut',show_img)
        # cv2.waitKey()


def H_projcet(img, h_pos):
    # print(thresh1[0,0])#250  输出[0,0]这个点的像素值 #返回值ret为阈值
    # print(ret)#130
    (h, w) = img.shape  # 返回高和宽
    # print(h,w)#s输出高和宽
    a = [0 for z in range(0, h)]
    for i in range(0, h):  # 每一行
        for j in range(0, w):  # 每一列
            if img[i, j] == 0:
                h_pos[i] += 1
                # img[i,j] = 255
                # for i in range(h):
                #     for j in range(0,h_pos[i]):
                #         thresh1[i,j] = 0
                # cv2.imshow('s',thresh1)
                # cv2.waitKey(0)


def V_project(line, v_pos):
    # img = cv2.imread(r'E:\keras_research\works\image\01.jpg')  # 读取图片，装换为可运算的数组
    # GrayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 将BGR图转为灰度图
    # ret, thresh1 = cv2.threshold(GrayImage, 130, 255, cv2.THRESH_BINARY)  # 将图片进行二值化（130,255）之间的点均变为255（背景）
    # print(thresh1[0,0])#250  输出[0,0]这个点的像素值  				#返回值ret为阈值
    # print(ret)#130
    (h, w) = line.shape  # 返回高和宽
    # print(h,w)#s输出高和宽
    # a = [0 for z in range(0, w)]
    # a = [0,0,0,0,0,0,0,0,0,0,...,0,0]初始化一个长度为w的数组，用于记录每一列的黑点个数


    # 记录每一列的波峰
    for j in range(0, w):  # 遍历一列
        for i in range(0, h):  # 遍历一行
            if line[i, j] == 0:  # 如果该点为黑点
                v_pos[j] += 1  # 该列的计数器加一计数
                # line[iq, j] = 255  # 记录完后将其变为白色
                # print (j)

    #
    # for j in range(0, w):  # 遍历每一列
    #     for i in range((h - v_pos[j]), h):  # 从该列应该变黑的最顶部的点开始向最底部涂黑
    #         line[i, j] = 0  # 涂黑

    # 此时的line便是一张图像向垂直方向上投影的直方图
    # 如果要分割字符的话，其实并不需要把这张图给画出来，只需要的到a=[]即可得到想要的
    # img2 =Image.open('0002.jpg')
    # img2.convert('L')
    # img_1 = np.array(img2)


def cutSingleChar(img):
    height, width = img.shape
    img_1 = cv2.imread(img)
    img0 = cv2.cvtColor(img_1, cv2.COLOR_RGB2GRAY)
    h_pos = [0 for _ in range(img0.shape[0])]
    h_peek_range = []
    H_projcet(img0, h_pos)
    Getpeekrange(h_pos, h_peek_range, 10, 10)
    lines = []
    for i in range(len(h_peek_range)):
        line = img[0:height, h_peek_range[i].begin:h_peek_range[i].begin + h_peek_range[i].end].copy()


class Program:
    def __init__(self, fi):
        self.img = fi
        self.lines = []

    def Main(self):
        """
        img_1:原图
        img0:灰图
        :return:
        """
        img_1 = cv2.imread(self.img)
        # img_1 = cv2.resize(img_1,(img_1.shape[0]*2,img_1.shape[1]*2))
        # img_1 = cv2.resize(img_1,img_1.size,2,2)
        img0 = cv2.cvtColor(img_1, cv2.COLOR_RGB2GRAY)
        # cv2.imshow('gray',img0)
        # 做一下膨胀 x,y方向都做
        print('img0_1:{}\n'.format(img0))
        img0 = cv2.bitwise_not(img0)
        print('img0_2:{}\n'.format(img0))
        kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7), (1, 1))
        # img = cv2.morphologyEx(img0,cv2.MORPH_CLOSE,kernel=kernel)
        img = cv2.dilate(img0,kernel)
        img = cv2.erode(img,(1,1))
        # cv2.imshow('err',img)
        ret, thresldImg = cv2.threshold(img, 160, 255, cv2.THRESH_BINARY)
        cv2.imshow('ss', thresldImg)
        cv2.waitKey(0)

        # 做连通性检测 每个连通域以一系列的点表示
        im2, contours, hierarchy = cv2.findContours(thresldImg, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
        for i in range(len(contours)):
            x, y, w, h = cv2.boundingRect(contours[i])
            height = 1 if y - h == 0 else (y - h)
            # if h-y > 0.02: # 比例>0.2
                # cv2.drawContours(img_1,contours,i,(0,255,0))
            cv2.rectangle(img_1, (x, y), (x + w, y + h), (0, 0, 255))
        # cv2.destroyAllWindows()
            # 非水平投影的文本行切割
            line = thresldImg[y:y+h,x:x+w]
            self.lines.append(line)
        # print('lines:{}\n,length:{}'.format(self.lines[0],len(self.lines)))

        char_set = []

        for i in range(len(self.lines)):
            line = self.lines[i]
            vertical_pos = [0 for _ in range(line.shape[1])]
            v_peek_range = []
            V_project(line,vertical_pos)
            print('vertical_pos:{},\n'.format(vertical_pos))
            Getpeekrange(vertical_pos,v_peek_range,7)
            print('v_peek_range:{}'.format(v_peek_range))
            cutChar(line,v_peek_range,char_set)
            del vertical_pos
            del v_peek_range
        return char_set


if __name__ == "__main__":
    fi = r'E:\keras_research\works\image\libai.JPG'
    # fi = r'E:\keras_research\works\08.PNG'
    ocr = Program(fi)
    char_set = ocr.Main()
    # for i in range(len(char_set)):
    #     pass
